import Renderer from '@/Render/Render';
import extentShader from '@/Render/Shader/extent.wgsl?raw';
import { Cartesian3, Matrix4, Transforms } from 'cesium';
// import { multiplyScalarWithMatrix4 } from '@/util/Matrix';
export default class Object3D {
    indexs: number[];
    vertices: number[];
    renderer: Renderer;
    vertexBuffer: GPUBuffer;
    indexBuffer: GPUBuffer;
    pipeline: GPURenderPipeline;
    bindGroup: GPUBindGroup;
    viewMatrixBuffer: GPUBuffer;
    modelMatrixBuffer: GPUBuffer;
    projectmatrixBuffer: GPUBuffer;
    /**
     *
     */
    constructor(renderer: Renderer, indexs: number[], vertices: number[]) {
        this.indexs = indexs;
        this.vertices = vertices;
        // this.vertices = [0, 0, 0, 1, 0, 0, 0, 1, 0];
        this.vertices = this.vertices.map(vertice => {
            return vertice * 100000
        })
        // console.log(this.vertices);
        // console.log(this.vertices);
        this.renderer = renderer;
        this.prearpareData()
    }
    /**
     * @description: 为webgpu渲染准备所需要的资.
     * 源
     */
    get indexLength() {
        return this.indexs.length;
    }

    prearpareData() {
        let verterxBuffer = this.renderer.device.createBuffer({
            size: this.vertices.length * 4,
            usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
            mappedAtCreation: true
        })
        new Float32Array(verterxBuffer.getMappedRange()).set(this.vertices)
        verterxBuffer.unmap()
        let indexBuffer = this.renderer.device.createBuffer({
            size: this.indexs.length * 4,
            usage: GPUBufferUsage.INDEX,
            mappedAtCreation: true
        })
        new Uint16Array(indexBuffer.getMappedRange()).set(this.indexs)
        indexBuffer.unmap()
        const bindGroupLayout = this.renderer.device.createBindGroupLayout({
            entries: [
                {
                    binding: 0,
                    visibility: GPUShaderStage.VERTEX, // 这些 uniform 变量在顶点着色器中使用
                    buffer: {
                        type: 'uniform',
                        hasDynamicOffset: false, // 假设这里不使用动态偏移量
                    },
                },
                {
                    binding: 1,
                    visibility: GPUShaderStage.VERTEX,
                    buffer: {
                        type: 'uniform',
                        hasDynamicOffset: false,
                    },
                },
                {
                    binding: 2,
                    visibility: GPUShaderStage.VERTEX,
                    buffer: {
                        type: 'uniform',
                        hasDynamicOffset: false,
                    },
                },
                // 其他绑定项...
            ],
        });
        const pipelineLayout = this.renderer.device.createPipelineLayout({
            bindGroupLayouts: [bindGroupLayout],
        });
        let pipeLine = this.renderer.device.createRenderPipeline({
            layout: pipelineLayout,
            vertex: {
                module: this.renderer.device.createShaderModule({
                    code: extentShader
                }),
                buffers: [{
                    arrayStride: 3 * 4,
                    attributes: [{
                        format: 'float32x3',
                        offset: 0,
                        shaderLocation: 0
                    }]
                }],
                entryPoint: 'vs_main'
            },
            primitive: {
                topology: 'triangle-list', // try point-list, line-list, line-strip, triangle-strip?
                // 开启背面剔除
                cullMode: 'back',
            },
            fragment: {
                module: this.renderer.device.createShaderModule({
                    code: extentShader
                }),
                entryPoint: 'fs_main',
                targets: [
                    {
                        format: 'bgra8unorm'
                    }
                ]
            }
        });
        const modelCenter = Cartesian3.fromDegrees(112, 23, 0);
        const modelMatrix = new Float32Array(Transforms.eastNorthUpToFixedFrame(modelCenter))

        const modelMatrixBuffer = this.renderer.device.createBuffer({
            size: 16 * 4,
            usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
            mappedAtCreation: true
        })
        new Float32Array(modelMatrixBuffer.getMappedRange()).set(modelMatrix)
        modelMatrixBuffer.unmap()
        const ViewMatrix = new Float32Array(this.renderer.camera.ViewMatrix);
        this.viewMatrixBuffer = this.renderer.device.createBuffer({
            size: 16 * 4,
            usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
            mappedAtCreation: true
        })
        new Float32Array(this.viewMatrixBuffer.getMappedRange()).set(ViewMatrix)
        this.viewMatrixBuffer.unmap()
        this.projectmatrixBuffer = this.renderer.device.createBuffer({
            size: 16 * 4,
            usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
            mappedAtCreation: true
        })
        const ProjectionMatrix = new Float32Array(this.renderer.camera.frustum.ProjectionMatrix);
        new Float32Array(this.projectmatrixBuffer.getMappedRange()).set(ProjectionMatrix)
        this.projectmatrixBuffer.unmap()
        this.bindGroup = this.renderer.device.createBindGroup({
            layout: pipeLine.getBindGroupLayout(0),
            entries: [
                {
                    binding: 0,
                    resource: {
                        buffer: modelMatrixBuffer
                    }
                },
                {
                    binding: 1,
                    resource: {
                        buffer: this.viewMatrixBuffer
                    }
                },
                {
                    binding: 2,
                    resource: {
                        buffer: this.projectmatrixBuffer
                    }
                }
            ]
        });
        this.vertexBuffer = verterxBuffer;
        this.indexBuffer = indexBuffer;
        this.pipeline = pipeLine;
    }

    setViewMatrix(viewMatrix: Matrix4) {
        this.renderer.device.queue.writeBuffer(this.viewMatrixBuffer, 0, new Float32Array(viewMatrix));
    }
    // setProjectMatrix(projectMatrix: Matrix4) {
    //     new Float32Array(this.projectmatrixBuffer.getMappedRange()).set(projectMatrix)
    //     this.projectmatrixBuffer.unmap()
    // }
}